package com.tanhua.server.service;

/**
 * @Author:Mr.yuan
 * @Description:
 * @Date: Created in 21:06 2021/1/16
 * @ModifiedBy:
 */


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Function;
import com.tanhua.server.enums.*;
import com.tanhua.server.mapper.*;
import com.tanhua.server.pojo.*;
import com.tanhua.server.utils.UserThreadLocal;
import com.tanhua.server.vo.IsLockEnum;
import com.tanhua.server.vo.LinHunVo;
import com.tanhua.server.vo.RportVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class TestLinHunService {

    @Autowired
    public TestLinHunMapper testLinHunMapper;
    @Autowired
    public TestLinHunOptionsMapper testLinHunOptionsMapper;

    @Autowired
    private UserQuestionMapper userQuestionMapper;
    @Autowired
    private ReportMapper reportMapper;
    @Autowired
    private LockMapper LockMapper;


    public List<LinHunVo> queryTestSoul() {
        List<LinHunVo> linHunVoList = new ArrayList<>();


        List<Questions> questions = this.testLinHunMapper.selectList(null);
        if (CollectionUtils.isEmpty(questions)) {
            return null;
        }
        questions.forEach(s -> s.setId(s.getIds().toString()));


        List<Options> options = this.testLinHunOptionsMapper.selectList(null);
        options.forEach(s -> s.setId(s.getIds().toString()));


        LambdaQueryWrapper<QuestionsLock> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QuestionsLock::getUserId, UserThreadLocal.get().getId());
        List<QuestionsLock> questionsLocks = LockMapper.selectList(wrapper);


        for (int i = 1; i <= 3; i++) {
            LinHunVo linHunVo = new LinHunVo();
            linHunVo.setId(i + "");
            switch (i) {
                case 1:
                    linHunVo.setName(NameEnum.NAME_1.getDesc());
                    linHunVo.setCover(CoverEnum.COVER_1.getValue());
                    linHunVo.setLevel(LevelEnum.Level_1.getDesc());
                    linHunVo.setStar(2);
                    linHunVo.setIsLock(IsLockEnum.LOCK_OFF.getValue());

                    if (CollectionUtils.isEmpty(questionsLocks)) {
                        QuestionsLock questionsLock = new QuestionsLock();
                        questionsLock.setIsLock(0);
                        questionsLock.setUserId(UserThreadLocal.get().getId());
                        questionsLock.setTest(1);
                        this.LockMapper.insert(questionsLock);
                    }
                    break;
                case 2:
                    linHunVo.setName(NameEnum.NAME_2.getDesc());
                    linHunVo.setCover(CoverEnum.COVER_2.getValue());
                    linHunVo.setLevel(LevelEnum.Level_2.getDesc());
                    linHunVo.setStar(3);
                    linHunVo.setIsLock(IsLockEnum.LOCK_ON.getValue());
                    if (CollectionUtils.isEmpty(questionsLocks)) {
                        QuestionsLock questionsLock = new QuestionsLock();
                        questionsLock.setIsLock(1);
                        questionsLock.setUserId(UserThreadLocal.get().getId());
                        questionsLock.setTest(2);
                        this.LockMapper.insert(questionsLock);
                    } else {
                        for (QuestionsLock questionsLock : questionsLocks) {
                            if (questionsLock.getTest() == 2) {
                                Integer isLock = questionsLock.getIsLock();
                                linHunVo.setIsLock(isLock);

                            }
                        }
                    }

                    break;

                case 3:
                    linHunVo.setName(NameEnum.NAME_3.getDesc());
                    linHunVo.setCover(CoverEnum.COVER_3.getValue());
                    linHunVo.setLevel(LevelEnum.Level_3.getDesc());
                    linHunVo.setStar(5);
                    linHunVo.setIsLock(IsLockEnum.LOCK_ON.getValue());
                    if (CollectionUtils.isEmpty(questionsLocks)) {
                        QuestionsLock questionsLock = new QuestionsLock();
                        questionsLock.setIsLock(1);
                        questionsLock.setUserId(UserThreadLocal.get().getId());
                        questionsLock.setTest(3);
                        this.LockMapper.insert(questionsLock);
                    } else {
                        for (QuestionsLock questionsLock : questionsLocks) {
                            if (questionsLock.getTest() == 3 && questionsLock.getUserId().equals(UserThreadLocal.get().getId())) {
                                Integer isLock = questionsLock.getIsLock();
                                linHunVo.setIsLock(isLock);

                            }
                        }
                    }
                    break;
            }


            List<Questions> que1 = new ArrayList<>();
            List<Questions> que2 = new ArrayList<>();
            List<Questions> que3 = new ArrayList<>();
            int count = 0;
            for (Questions question : questions) {
                ArrayList<Options> opt = new ArrayList<>();

                for (Options option : options) {
                    if (question.getId().equals(option.getQid())) {
                        opt.add(option);
                    }
                }
                Options[] array = opt.toArray(new Options[0]);
                question.setOptions(array);

                if (count < 10) {
                    que1.add(question);
                } else if (count >= 10 && count < 20) {
                    que2.add(question);

                } else if (count >= 20) {
                    que3.add(question);
                }
                count++;
            }

            if (i == 1) {
                linHunVo.setQuestions(que1.toArray());
            } else if (i == 2) {
                linHunVo.setQuestions(que2.toArray());
            } else if (i == 3) {
                linHunVo.setQuestions(que3.toArray());

            }

            linHunVoList.add(linHunVo);

        }

        return linHunVoList;
    }

    private Set<String> getLock(List<Integer> list) {
        List<UserQuestion> userQuestions = null;
        Integer testid = 1;
        try {
            LambdaQueryWrapper<UserQuestion> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserQuestion::getUserId, UserThreadLocal.get().getId());
            wrapper.in(UserQuestion::getQuestionId, list);
            userQuestions = userQuestionMapper.selectList(wrapper);


        } catch (Exception e) {
            UserQuestion userQuestion = new UserQuestion();
        }
        return userQuestions.stream().map(UserQuestion::getQuestionId).collect(Collectors.toSet());
    }

    public String testSoul(ArrayList<UserQuestion> list) {
        User user = UserThreadLocal.get();
        List<Integer> lists = new ArrayList<>();


        Set<String> collect = list.stream().map(UserQuestion::getQuestionId).collect(Collectors.toSet());
        Set<Integer> ids = new HashSet<>();
        for (String s : collect) {
            ids.add(Integer.parseInt(s));
        }
        LambdaQueryWrapper<UserQuestion> w = new LambdaQueryWrapper<>();
        w.eq(UserQuestion::getUserId, UserThreadLocal.get().getId());
        w.in(UserQuestion::getQuestionId, ids);
        List<UserQuestion> userQuestions = this.userQuestionMapper.selectList(w);

        if (!CollectionUtils.isEmpty(userQuestions)) {
            for (UserQuestion question : userQuestions) {
                String questionId = question.getQuestionId();
                lists.add(Integer.parseInt(questionId));
                for (UserQuestion userQuestion : list) {
                    userQuestion.setUserId(user.getId());
                    QueryWrapper<Options> wrapper = new QueryWrapper<>();
                    wrapper.eq("id", userQuestion.getOptionId());
                    Options options = this.testLinHunOptionsMapper.selectOne(wrapper);
                    if (options.getQid().equals(question.getQuestionId())) {
                        LambdaUpdateWrapper<UserQuestion> score = new LambdaUpdateWrapper<>();
                        score.eq(UserQuestion::getQuestionId, question.getId())
                                .set(UserQuestion::getScore, options.getScore());


                        int update = userQuestionMapper.update(null, score);
                    }

                }


            }
        }

        if (CollectionUtils.isEmpty(userQuestions)) {
            for (UserQuestion userQuestion : list) {
                userQuestion.setUserId(user.getId());
                QueryWrapper<Options> wrapper = new QueryWrapper<>();
                wrapper.eq("id", userQuestion.getOptionId());
                Options options = this.testLinHunOptionsMapper.selectOne(wrapper);
                userQuestion.setScore(options.getScore());

                String questionId = userQuestion.getQuestionId();
                lists.add(Integer.parseInt(questionId));

                userQuestionMapper.insert(userQuestion);
            }
        }
        Integer test = 1;
        if (lists.get(0) > 10) {
            test = 2;
        }
        Set<String> questionIds = getLock(lists);
        if (questionIds.size() == 10) {
            LambdaUpdateWrapper<QuestionsLock> up = new LambdaUpdateWrapper<>();
            up.eq(QuestionsLock::getUserId, UserThreadLocal.get().getId())
                    .eq(QuestionsLock::getTest, test + 1)
                    .set(QuestionsLock::getIsLock, 0);
            int update = this.LockMapper.update(null, up);

        }

        if (lists.get(0) > 20) {
            test = 3;
        }

        return InsertReport(questionIds, test);


    }

    private String InsertReport(Set<String> collect, Integer integer) {

        if (collect.size() == 10) {
            Report report = new Report();
            report.setUserId(UserThreadLocal.get().getId());
            Long scoreSum = getScoreSum(collect);
            report.setScoreSum(scoreSum.intValue());
            report.setTest(integer);
            this.reportMapper.insert(report);

            LambdaQueryWrapper<Report> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Report::getUserId, UserThreadLocal.get().getId());

            List<Report> reports = reportMapper.selectList(wrapper);
            Collections.sort(reports, (o1, o2) -> o2.getId() - o1.getId());
            Report report1 = reports.get(0);
            return report1.getId().toString();

        }

        return null;
    }


    private Long getScoreSum(Set<String> collect1) {
        LambdaQueryWrapper<UserQuestion> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserQuestion::getUserId, UserThreadLocal.get().getId());
        wrapper.in(UserQuestion::getQuestionId, collect1);
        List<UserQuestion> userQuestions = this.userQuestionMapper.selectList(wrapper);
        return userQuestions.stream().mapToLong(UserQuestion::getScore).sum();


    }


    @Autowired
    private UserInfoService userInfoService;

    public RportVo queryReport(String id) {

        LambdaQueryWrapper<Report> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Report::getId, id);
        Report report = this.reportMapper.selectOne(wrapper);

        RportVo rportVo = new RportVo();
        rportVo.setId(report.getId().toString());
        if (report.getScoreSum() < 21) {
            rportVo.setConclusion(Conclusion.Conclusion_1.getValue());
            rportVo.setCover(Cover.Cover_1.getValue());
        } else if (report.getScoreSum() >= 21 && report.getScoreSum() <= 40) {
            rportVo.setConclusion(Conclusion.Conclusion_2.getValue());
            rportVo.setCover(Cover.Cover_2.getValue());

        } else if (report.getScoreSum() >= 41 && report.getScoreSum() <= 55) {
            rportVo.setConclusion(Conclusion.Conclusion_3.getValue());
            rportVo.setCover(Cover.Cover_3.getValue());
        } else if (report.getScoreSum() >= 56) {
            rportVo.setConclusion(Conclusion.Conclusion_4.getValue());
            rportVo.setCover(Cover.Cover_4.getValue());
        }

        List<Dimensions> dimensionsList = new ArrayList<>();
        Dimensions dimensions1 = new Dimensions(KeyEnum.Key_1.getValue(), ValueEnum.Value_1.getValue());
        Dimensions dimensions2 = new Dimensions(KeyEnum.Key_2.getValue(), ValueEnum.Value_2.getValue());
        Dimensions dimensions3 = new Dimensions(KeyEnum.Key_3.getValue(), ValueEnum.Value_3.getValue());
        Dimensions dimensions4 = new Dimensions(KeyEnum.Key_4.getValue(), ValueEnum.Value_4.getValue());

        dimensionsList.add(dimensions1);
        dimensionsList.add(dimensions2);
        dimensionsList.add(dimensions3);
        dimensionsList.add(dimensions4);
        Object[] dimensions = dimensionsList.toArray();
        rportVo.setDimensions(dimensions);


        LambdaQueryWrapper<Report> wrappers = new LambdaQueryWrapper<>();


        String conclusion = rportVo.getConclusion();
        if (conclusion.equals(Conclusion.Conclusion_1.getValue())) {
            wrapper.between(Report::getScoreSum, 0, 21);
        } else if (conclusion.equals(Conclusion.Conclusion_2.getValue())) {
            wrapper.between(Report::getScoreSum, 21, 41);
        } else if (conclusion.equals(Conclusion.Conclusion_3.getValue())) {
            wrapper.between(Report::getScoreSum, 41, 55);
        } else if (conclusion.equals(Conclusion.Conclusion_4.getValue())) {
            wrapper.between(Report::getScoreSum, 55, 100);
        }

        Page<Report> page = new Page<>(1, 50);
        IPage<Report> reportIPage = this.reportMapper.selectPage(page, wrappers);
        List<Report> reports = reportIPage.getRecords();

       // List<Report> reports = this.reportMapper.selectList(wrappers);
        if (reports.size() > 10) {
            reports = reports.stream().limit(10).collect(Collectors.toList());
        } else if (reports.size() == 0) {
            return rportVo;
        }

        Set<Long> collect = reports.stream().map(Report::getUserId).collect(Collectors.toSet());

        QueryWrapper<UserInfo> query = new QueryWrapper<>();
        query.in("user_id", collect);
        List<UserInfo> userInfos = userInfoService.queryUserInfoList(query);


        List<SimilarYou> similarYous = new ArrayList<>();
        for (UserInfo userInfo : userInfos) {
            if (!userInfo.getUserId().equals(UserThreadLocal.get().getId())) {
                SimilarYou similarYou = new SimilarYou();
                similarYou.setId(userInfo.getUserId());

                similarYou.setAvatar(userInfo.getLogo());
                similarYous.add(similarYou);

            }
        }

        Object[] similar = similarYous.toArray();

        rportVo.setSimilarYou(similar);


        return rportVo;
    }
}
